﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Drawing.Printing;
using System.Drawing;
using System.Collections;

namespace Joyeon.Utils
{
    public static class PrinterUtil
    {
        public static List<string> GetPhysicalPrinters()            //此方法为新打印机功能调用，获取当前系统中安装的打印机
        {
            List<string> fPrinters = new List<string>();
            //foreach (String fPrinterName in PrinterSettings.InstalledPrinters)
            //{
            //    fPrinters.Add(fPrinterName);
            //}
            fPrinters.AddRange((IEnumerable<String>)PrinterSettings.InstalledPrinters);
            return fPrinters;
        }
        /// <summary>
        /// 调用打印机的打印方法
        /// </summary>
        /// <param name="printer"></param>
        public static void Print(Printer printer)
        {
            if (printer!=null)
            {
                printer.Print();
            }
        }
        /// <summary>
        /// 打印机类
        /// </summary>
        public class Printer
        {
            private String printerName = null;
            PrintDocument docToPrint = new PrintDocument();
            private APrinterItemCollection itemsSource = new APrinterItemCollection();

            public APrinterItemCollection ItemsSource
            {
                get { return itemsSource; }
                set { itemsSource = value; }
            }

            public event EventHandler OnDocumentEndPrint;

            private float paddingLeft = 10;
            private float paddingTop = 10;
            private float printFontSize = 10;
            private float printLineHeight = 20;
            private Font font;
            private Brush brush;

            /// <summary>
            /// 执行打印的方法
            /// </summary>
            public void Print()
            {
                //根据用户的选择，开始打印
                //创建一个PrintDialog的实例
                try
                {
                    docToPrint.PrintController = new System.Drawing.Printing.StandardPrintController();
                    docToPrint.Print();//开始打印
                }
                catch (System.Exception ex)
                {
                    Console.WriteLine("打印错误:\n错误信息:\n" + ex.Message);
                }
            }
            
            /// <summary>
            /// 构造方法
            /// throws ArgumentException
            /// </summary>
            /// <param name="printerName"></param>
            public Printer(String printerName) 
            {
                if (StringUtil.IsNullOrEmptyOrWhiteSpace(printerName))
                {
                    throw new ArgumentException("Printer name is null or empty!");
                }
                this.printerName = printerName;
                docToPrint.PrinterSettings.PrinterName = printerName;
                docToPrint.PrintPage += new System.Drawing.Printing.PrintPageEventHandler(docToPrint_PrintPage);
                docToPrint.EndPrint += new PrintEventHandler(docToPrint_EndPrint);
                this.font = new System.Drawing.Font("Arial", printFontSize, System.Drawing.FontStyle.Regular);
                this.brush = System.Drawing.Brushes.Black;
            }

            //设置打印机开始打印的事件处理函数
            private void docToPrint_PrintPage(object sender, System.Drawing.Printing.PrintPageEventArgs e)
            {
                e.HasMorePages = true;
                int length = this.itemsSource.Count;
                for (int i = 0; i < length; i++)
                {
                    APrinterItem item = itemsSource[i];
                    e.Graphics.DrawString(item.Text, item.Font,item.Brush, item.Left, item.Top);
                }
                e.HasMorePages = false;
            }
            
            /// <summary>
            /// 打印结束时的事件处理
            /// </summary>
            /// <param name="sender"></param>
            /// <param name="e"></param>
            void docToPrint_EndPrint(object sender, PrintEventArgs e)
            {
                if (OnDocumentEndPrint != null)
                {
                    OnDocumentEndPrint(this, new EventArgs());
                }
            }

            /// <summary>
            /// 创建一个打印机条目，使用打印机默认配置。
            /// </summary>
            /// <returns></returns>
            public APrinterItem CreateDefaultPrinterItem(String text) 
            {
                return this.CreatePrinterItem(text, this.paddingLeft, this.paddingTop, this.printLineHeight, this.font, this.brush);
            }

            /// <summary>
            /// 创建一个打印条目
            /// </summary>
            /// <param name="text"></param>
            /// <param name="left"></param>
            /// <param name="top"></param>
            /// <param name="lineHeight"></param>
            /// <param name="font"></param>
            /// <param name="brush"></param>
            /// <returns></returns>
            public APrinterItem CreatePrinterItem(String text, float? left = null, float? top = null, float? lineHeight = null, Font font = null, Brush brush=null) 
            {
                if (text==null)
                {
                    throw new ArgumentNullException("Parameter 'text' is null!");
                }
                return new PrinterItem(text, font == null ? this.font : font, brush == null ? this.brush : brush, left == null ? this.paddingLeft : left.Value, top == null ? this.paddingTop : top.Value, lineHeight == null ? this.printLineHeight : lineHeight.Value);
            }

            private class PrinterItem :APrinterItem
            {
                public PrinterItem(String text,Font font,Brush brush,float left,float top,float lineHeight) 
                {
                    this.Text = text;
                    this.Font = font;
                    this.Brush = brush;
                    this.Left = left;
                    this.Top = top;
                    this.LineHeight = lineHeight;
                }
            }

            public class APrinterItemCollection : ICollection, IEnumerable
            {
                private static object syncRoot = new object();

                List<APrinterItem> items = new List<APrinterItem>();
                private int index = -1;

                /// <summary>
                /// 添加一个条目
                /// </summary>
                /// <param name="item"></param>
                public void Add(APrinterItem item) 
                {
                    if (item != null)
                    {
                        lock (syncRoot)
                        {
                            if (index > -1)
                            {
                                item.Top = items[index].LineHeight + items[index].Top;
                            }
                            items.Add(item);
                            index++;
                        }
                    }
                }
                /// <summary>
                /// 删除指定引用的条目
                /// </summary>
                /// <param name="item"></param>
                /// <returns></returns>
                public APrinterItem Remove(APrinterItem item)
                {
                    if (item!=null)
                    {
                        lock (syncRoot) 
                        {
                            return this.RemoveAt(this.items.IndexOf(item));
                        }
                    }
                    else
                    {
                        return null;
                    }
                }

                /// <summary>
                /// 删除指定位置的条目
                /// </summary>
                /// <param name="index"></param>
                /// <returns></returns>
                public APrinterItem RemoveAt(int index)
                {
                    APrinterItem deleteItem = null;
                    if (this.index >= index)
                    {
                        deleteItem = this.items[index];
                        this.items.RemoveAt(index);
                        IList<APrinterItem> list = this.items;
                        this.Clear();
                        foreach (APrinterItem item in list)
                        {
                            this.Add(item);
                        }
                    }
                    return deleteItem;
                }

                /// <summary>
                /// 清空打印列表 
                /// </summary>
                public void Clear()
                {
                    this.index = -1;
                    this.items = new List<APrinterItem>();
                }

                /// <summary>
                /// 将另一个集合中的所有元素添加到当前集合中。
                /// </summary>
                /// <param name="collection"></param>
                public void AddRange(APrinterItemCollection collection)
                {
                    if (collection!=null)
                    {
                        this.AddRange(collection, 0, collection.Count);
                    }
                }

                /// <summary>
                /// 将另一个集合中从指定位置开始的指定个数元素添加到当前集合中。
                /// </summary>
                /// <param name="collection">源集合</param>
                /// <param name="startIndex">起始位置</param>
                /// <param name="length">元素个数</param>
                public void AddRange(APrinterItemCollection collection,int startIndex,int length) 
                {
                    if (collection!=null)
                    {
                        length = startIndex + length;
                        for (int i = startIndex; i < length&&i<collection.Count; i++)
                        {
                            this.Add(collection[i]);
                        }
                    }
                }

                /// <summary>
                /// 通过下标访问当前集合中的元素 
                /// </summary>
                /// <param name="index"></param>
                /// <returns></returns>
                public APrinterItem this[int index]
                {
                    get
                    {
                        return this.items[index];
                    }
                }

                /// <summary>
                /// 获得集合的长度
                /// </summary>
                public int Count 
                {
                    get { return this.index + 1; }
                }

                public IEnumerator GetEnumerator()
                {
                    return (IEnumerator)this;
                }

                public void CopyTo(Array array, int index)
                {
                    throw new NotImplementedException();
                }

                public bool IsSynchronized
                {
                    get { return true; }
                }

                public object SyncRoot
                {
                    get { return syncRoot; }
                }
            }
        }
        /// <summary>
        /// 打印机条目类信息
        /// </summary>
        public abstract class APrinterItem
        {
            private String text;

            /// <summary>
            /// 所要打印的文本
            /// </summary>
            public String Text
            {
                get { return text; }
                set { text = value; }
            }
            private Font font;

            /// <summary>
            /// 字体
            /// </summary>
            public Font Font
            {
                get { return font; }
                set { font = value; }
            }
            private Brush brush;

            /// <summary>
            /// 颜色
            /// </summary>
            public Brush Brush
            {
                get { return brush; }
                set { brush = value; }
            }
            private float left;

            /// <summary>
            /// 距离纸张左边的距离
            /// </summary>
            public float Left
            {
                get { return left; }
                set { left = value; }
            }
            private float top;

            /// <summary>
            /// 距离纸张顶端的距离
            /// </summary>
            public float Top
            {
                get { return top; }
                set { top = value; }
            }

            private float lineHeight;

            /// <summary>
            /// 行高
            /// </summary>
            public float LineHeight
            {
              get { return lineHeight; }
              set { lineHeight = value; }
            }
        }
    }
    
        
}
